//#ifndef EIGEN_USE_MKL_ALL
//#define EIGEN_USE_MKL_ALL
//#endif

#include <Eigen/Dense>
#include <iostream>
#include "../data_collector/data_collector.hpp"
#include <cmath>
#include <set>
#include <ctime>

using namespace std;

struct Sigmoid
{
	double operator()(double x) const
	{
		return 1 / (1 + exp(-x));
	}
};

void binLabel(VectorXd &Y)
{
	set<double> l;
	for (int i = 0; i < Y.size(); i++)
		l.insert(Y(i));
	for (int i = 0; i < Y.size(); i++)
	{
		if (Y(i) == *l.cbegin())
			Y(i) = 0;
		else
			Y(i) = 1;
	}
	//#ifdef _DEBUG
	//	cout << Y << endl;
	//#endif // _DEBUG

}


VectorXd gradDesc(const MatrixXd& labeledData, double xi, double eta)
{
	srand((unsigned)std::time(NULL));
	MatrixXd X = labeledData.block(0, 0, labeledData.rows() - 1, labeledData.cols()).transpose().eval();
	X.conservativeResize(X.rows(), X.cols() + 1);
	X.col(X.cols() - 1) = VectorXd::Ones(X.rows());

	VectorXd Y = labeledData.row(labeledData.rows() - 1).transpose().eval();
	binLabel(Y);

	VectorXd W = VectorXd::Ones(X.cols());
	VectorXd old_Y, error;
	do//deduce from MLE 
	{
		old_Y = (X*W).unaryExpr(Sigmoid()).eval();
		error = Y - old_Y;
		W += eta*X.transpose()*error;
	} while (error.squaredNorm() > xi);
	cout << W.transpose() << endl;

	return W;
}

int main()
{
	DataCollector d;
	d.readDataFromFile("iris.data");


	d.DataList()->conservativeResize(5, 100);
	VectorXd tmp = gradDesc(*d.DataList(), 0.001, -1);
	MatrixXd y = d.DataList()->block(0, 0, d.DataList()->rows() - 1, d.DataList()->cols()).transpose();
	y.conservativeResize(y.rows(), y.cols() + 1);
	y.col(y.cols() - 1) = VectorXd::Ones(y.rows());
	cout << (y*tmp).unaryExpr(Sigmoid()) << endl;
	return 0;
}